#include<func.h>

//Node 和list
typedef struct node_s
{
    int num;
    struct node_s* pNext;
}Node;

typedef struct list
{
    int Length;
    Node *pTail;
    Node *pHead;
}List;

//尾插法 int 返回值检查报错
int AddTail(List *list,int num)
{
    Node *node = (Node*)malloc(sizeof(Node));
    node->num =num;
    node->pNext = NULL;
    if(list->Length == 0)
    {
        list->pHead =node;
        list->pTail = node;
    }
    else
    {
        list->pTail->pNext = node;
        list->pTail =node;
    }
    ++list->Length;
    return 0;
}

//头删法
int deletHead(List *list)
{
    Node *pcur = list->pHead;
    list->pHead = pcur->pNext;
    if(list->Length == 1)
    {
        list->pTail == NULL;
    }
    free(pcur);
    --list->Length;
    return 0;
}

//查看链表
int VistList(List *list)
{
    Node *pTemp = list->pHead;
    while(pTemp)
    {
        printf("%4d",pTemp->num);
        pTemp = pTemp->pNext;
    }
    printf("\n");
    return 0;
}


//共享数据部分
typedef struct Share_s
{
    List list;
    pthread_mutex_t mutex;
    pthread_cond_t cond;
}Share_t;

//生产者
void* Pro_pthreadFunc(void*args)
{
    //接收变量
    Share_t *share = (Share_t *)args;
    // >10 的时候 停止生产 同时唤醒所有线程
    while(1)
    {
        pthread_mutex_lock(&share->mutex);
        while(share->list.Length >= 10)
        {
            //解锁 + 退出
            pthread_cond_wait(&share->cond,&share->mutex);
            break;
        }
        //开始生产
        int num =rand()%1001;
        printf("produce num = %d\n",num);
        AddTail(&share->list,num); //此时生产成功
        VistList(&share->list);
        pthread_mutex_unlock(&share->mutex);
        
        //通知
        pthread_mutex_lock(&share->mutex);
        pthread_cond_broadcast(&share->cond);
        pthread_mutex_unlock(&share->mutex);

        sleep(2);
    }
    pthread_exit(NULL);
}

//消费者
void* Cons_pthreadFunc(void*args)
{
    Share_t *share = (Share_t*)args;
    // <= 0的时候等待 消费一个就提醒一次
    while(1)
    {
        pthread_mutex_lock(&share->mutex);
        while(share->list.Length <= 0)
        {
            pthread_cond_wait(&share->cond,&share->mutex);
            break;
        }
        
        //消费
        printf("cons num =%d\n",share->list.pHead->num);
        deletHead(&share->list);
        VistList(&share->list);
        pthread_mutex_unlock(&share->mutex);

        //通知其他线程判断
        pthread_mutex_lock(&share->mutex);
        pthread_cond_broadcast(&share->cond);
        pthread_mutex_unlock(&share->mutex);

        sleep(1);
    }
    pthread_exit(NULL);
}

//主线程
int main(void)
{
    //初始化各个数据
    Share_t share;
    memset(&share.list,0,sizeof(share));

    for(int i =0;i<8;i++)
    {
        int num =rand()%1001;
        AddTail(&share.list,num);
        VistList(&share.list);
    }

    //锁和条件变量初始化
    pthread_mutex_init(&share.mutex,NULL);
    pthread_cond_init(&share.cond,NULL);

    //创建子线程
    pthread_t pro1,pro2,pro3;
    pthread_t cons1,cons2;

    //生产者
    pthread_create(&pro1,NULL,&Pro_pthreadFunc,&share);
    pthread_create(&pro2,NULL,&Pro_pthreadFunc,&share);
    pthread_create(&pro3,NULL,&Pro_pthreadFunc,&share);

    //消费者
    pthread_create(&cons1,NULL,&Cons_pthreadFunc,&share);
    pthread_create(&cons2,NULL,&Cons_pthreadFunc,&share);

    //等待
    pthread_join(pro1,NULL);
    pthread_join(pro2,NULL);
    pthread_join(pro3,NULL);

    pthread_join(cons1,NULL);
    pthread_join(cons2,NULL);

    return 0;
}